package com.xnyzc.lhy.order.service.impl.user.wallet;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xnyzc.lhy.common.component.convert.DateToStringConverter;
import com.xnyzc.lhy.common.entity.Rv;
import com.xnyzc.lhy.common.exception.PangException;
import com.xnyzc.lhy.common.penum.EErrorCode;
import com.xnyzc.lhy.common.penum.EOrderType;
import com.xnyzc.lhy.common.penum.order.EOrderNoType;
import com.xnyzc.lhy.common.penum.vehicle.EvehicleType;
import com.xnyzc.lhy.common.penum.wallet.EAvailableTimeType;
import com.xnyzc.lhy.common.penum.wallet.EIsTransaction;
import com.xnyzc.lhy.common.penum.wallet.ERecordType;
import com.xnyzc.lhy.common.util.CheckUtil;
import com.xnyzc.lhy.order.entity.area.OaSysOpenArea;
import com.xnyzc.lhy.order.entity.result.user.WalletRecordResult;
import com.xnyzc.lhy.order.entity.sidebar.OaCUserOffice;
import com.xnyzc.lhy.order.entity.user.OaCUserMode;
import com.xnyzc.lhy.order.entity.user.wallet.OaCWalletRecord;
import com.xnyzc.lhy.order.mapper.area.OaSysOpenAreaMapper;
import com.xnyzc.lhy.order.mapper.sidebar.OaCUserOfficeMapper;
import com.xnyzc.lhy.order.mapper.user.OaCUserModeMapper;
import com.xnyzc.lhy.order.mapper.user.wallet.OaCWalletRecordMapper;
import com.xnyzc.lhy.order.service.user.wallet.IOaCWalletRecordService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 用户钱包记录表 服务实现类
 * </p>
 *
 * @author zhuyubin
 * @since 2019-07-19
 */
@Service
public class OaCWalletRecordServiceImpl extends ServiceImpl<OaCWalletRecordMapper, OaCWalletRecord> implements IOaCWalletRecordService {

    @Autowired
    private OaCWalletRecordMapper oaCWalletRecordMapper;
    @Autowired
    private OaCUserOfficeMapper oaCUserOfficeMapper;
    @Autowired
    private OaCUserModeMapper oaCUserModeMapper;
    @Autowired
    private OaSysOpenAreaMapper oaSysOpenAreaMapper;

    /**
     * 获取账单列表
     * @param userId 用户id
     * @param tag 租户
     * @param type 0充值1收入
     * @param current 分页当前页从1开始
     * @return
     */
    @Override
    public IPage selectWalletRecordPage(Long userId, String tag, Integer type, Long current){
        // 收入
        if (type.equals(1)){
            return this.selectWalletRecordPageByRecordType(userId, tag, current,
                    ERecordType.moneyTopUp.getType(),
                    ERecordType.alipayTopUp.getType(),
                    ERecordType.weChatTopUp.getType()
            );
        }
        // 支出
        else if (type.equals(0)){
            return this.selectWalletRecordPageByRecordType(userId, tag, current,
                    ERecordType.moneyDisbursement.getType(),
                    ERecordType.alipayDisbursement.getType(),
                    ERecordType.weChatDisbursement.getType()
            );
        }
        return new Page();
    }

    /**
     * 获取个人或部门公务列表
     * @param userId 用户id
     * @param tag 租户
     * @param type 0个人1部门
     * @param current 分页当前页从1开始
     * @return
     */
    @Override
    public IPage selectPersonageOrOfficialPage(Long userId, String tag, Integer type, Long current){
        // 收入
        if (type.equals(0)){
            return this.selectWalletRecordPageByRecordType(userId, tag, current,
                    ERecordType.myTopUp.getType(),
                    ERecordType.myDisbursement.getType()
            );
        }
        // 支出
        else if (type.equals(1)){
            return this.selectWalletRecordPageByRecordType(userId, tag, current,
                    ERecordType.officialTopUp.getType(),
                    ERecordType.officialDisbursement.getType()
            );
        }
        return new Page();
    }

    /**
     * 账单详情
     * @param userId 用户id
     * @param tag 租户
     * @param recordId 账单id
     * @return
     */
    @Override
    public Map<String, Object> getWalletRecord(Long userId, String tag, Long recordId){
        Map<String, Object> map = this.initWalletRecord();
        OaCWalletRecord oaCWalletRecord = oaCWalletRecordMapper.selectOne(
                Wrappers.<OaCWalletRecord>lambdaQuery()
                        .eq(OaCWalletRecord::getUserId, userId)
                        .eq(OaCWalletRecord::getTag, tag)
                        .eq(OaCWalletRecord::getRecordId, recordId)
        );
        if (CheckUtil.objIsEmpty(oaCWalletRecord)){
            return map;
        }
        ERecordType recordType = ERecordType.findById(oaCWalletRecord.getRecordType());
        // 0是充值
        if (recordType.getRecordType().equals(0)){
            map.put("actualAmount", String.format("+ %s", oaCWalletRecord.getActualAmount().toString()));
        } else {
            map.put("actualAmount", String.format("- %s", oaCWalletRecord.getActualAmount().toString()));
        }
        String orderNo = oaCWalletRecord.getOrderNo();
        if (CheckUtil.objIsNotEmpty(orderNo)){
            map.put("costDesc", String.format("%s %s", EOrderType.findByOrderType(orderNo), orderNo));
        } else {
            map.put("costDesc", recordType.getValue());
        }
        map.put("recordType", ERecordType.findById(oaCWalletRecord.getRecordType()).getValue());
        map.put("isTransaction", EIsTransaction.findById(oaCWalletRecord.getIsTransaction()).getDesc());
        map.put("transactionTime", new DateToStringConverter().convert(oaCWalletRecord.getTransactionTime()));
        map.put("transactionSerialNo", CheckUtil.strIsEmpty(oaCWalletRecord.getTransactionOrderNo()) ? oaCWalletRecord.getOrderNo() : oaCWalletRecord.getTransactionOrderNo());
        return map;
    }

    /**
     * 获取用车制度
     * @param userId 用户id
     * @param tag 租户
     * @return
     */
    @Override
    public Map<String, Object> getVehicleSystem(Long userId, String tag){
        Map<String, Object> map = this.initVehicleSystem();
        OaCUserOffice oaCUserOffice = oaCUserOfficeMapper.selectOne(
                Wrappers.<OaCUserOffice>lambdaQuery()
                        .eq(OaCUserOffice::getUserId, userId)
                        .eq(OaCUserOffice::getTag, tag)
        );
        if (CheckUtil.objIsEmpty(oaCUserOffice)){
            return map;
        }
        OaCUserMode oaCUserMode = oaCUserModeMapper.selectOne(
                Wrappers.<OaCUserMode>lambdaQuery()
                        .eq(OaCUserMode::getTag, tag)
                        .eq(OaCUserMode::getOfficeId, oaCUserOffice.getOfficeId())
        );
        if (CheckUtil.objIsEmpty(oaCUserMode)){
            return map;
        }
        map.put("availableTime", EAvailableTimeType.findById(oaCUserMode.getAvailableTime()).getValue());
        // 可用车型从枚举中取
        String availableModel = oaCUserMode.getAvailableModel();
        if (CheckUtil.objIsNotEmpty(availableModel)){
            if (availableModel.contains(",")){
                String[] availableModels = availableModel.split(",");
                StringBuffer stringBuffer = new StringBuffer();
                for (String vehType : availableModels) {
                    stringBuffer.append(EvehicleType.findById(Integer.valueOf(vehType))).append(",");
                }
                stringBuffer.deleteCharAt(stringBuffer.length() - 1);
                map.put("availableModel", stringBuffer.toString());
            } else {
                map.put("availableModel", EvehicleType.findById(Integer.valueOf(availableModel)));
            }
        }
        // 可用城市从开通城市表中查
        String availableCity = oaCUserMode.getAvailableCity();
        if (CheckUtil.objIsNotEmpty(availableCity)){
            if (availableCity.contains(",")){
                String[] availableCitys = availableCity.split(",");
                List<String> cityCodes = new ArrayList<>();
                for (String city : availableCitys) {
                    cityCodes.add(city);
                }
                List<OaSysOpenArea> oaSysOpenAreas = oaSysOpenAreaMapper.selectList(Wrappers.<OaSysOpenArea>lambdaQuery().eq(OaSysOpenArea::getTag, tag).in(OaSysOpenArea::getCityId, cityCodes));
                StringBuffer stringBuffer = new StringBuffer();
                for (OaSysOpenArea oaSysOpenArea : oaSysOpenAreas) {
                    stringBuffer.append(oaSysOpenArea).append(",");
                }
                stringBuffer.deleteCharAt(stringBuffer.length() - 1);
                map.put("availableCity", stringBuffer.toString());
            } else {
                map.put("availableCity", EvehicleType.findById(Integer.valueOf(availableModel)));
            }
        }
        map.put("availableCity", oaCUserMode.getAvailableCity());
        return map;
    }

    @Override
    public Rv getRechargeRecord(Long userId, String tag,
                                Integer type, Integer pageIndex, Integer pageSize) {

        if (type==null){
            throw PangException.create(EErrorCode.missingArg);
        }
        if(pageIndex==null||pageIndex<1){
            pageIndex=1;
        }
        if(pageSize==null||pageSize<1||pageSize>100){
            pageSize=10;
        }
        Map<String,Object> map=new HashMap<>();
        if(type==0){
            map= getRechargeRecord( userId,  tag,  pageIndex, pageSize,
                    ERecordType.moneyTopUp.getType(),
                    ERecordType.alipayTopUp.getType(),
                    ERecordType.weChatTopUp.getType(),
                    ERecordType.officialTopUp.getType(),
                    ERecordType.myTopUp.getType(),
                    ERecordType.compensation.getType(),
                    ERecordType.reward.getType(),
                    ERecordType.changePrice.getType(),
                    ERecordType.withdrawalBack.getType()
                    );
        }else if(type==1){
            map= getRechargeRecord( userId,  tag,  pageIndex, pageSize,
                    ERecordType.moneyDisbursement.getType(),
                    ERecordType.alipayDisbursement.getType(),
                    ERecordType.weChatDisbursement.getType(),
                    ERecordType.officialDisbursement.getType(),
                    ERecordType.myDisbursement.getType(),
                    ERecordType.fine.getType(),
                    ERecordType.withdrawal.getType(),
                    ERecordType.refund.getType()
            );
        }
        return  Rv.wrap(map);
    }

    private Map<String,Object> getRechargeRecord(Long userId, String tag, Integer pageIndex,Integer pageSize,  Integer... recordType){
        IPage<OaCWalletRecord> oaCWalletRecordIPage = new Page<>();
        oaCWalletRecordIPage.setCurrent(pageIndex);
        oaCWalletRecordIPage.setSize(pageSize);
        // 钱包记录
        oaCWalletRecordIPage = oaCWalletRecordMapper.selectPage(oaCWalletRecordIPage,
                Wrappers.<OaCWalletRecord>lambdaQuery()
                        .eq(OaCWalletRecord::getUserId, userId)
                        .eq(OaCWalletRecord::getTag, tag)
                        .eq(OaCWalletRecord::getIsTransaction, EIsTransaction.paySuccess.getValue())
                        .in(OaCWalletRecord::getRecordType, recordType)
                        .orderByDesc(OaCWalletRecord::getCreateTime)
        );
        List<WalletRecordResult> list = new ArrayList();
        for (OaCWalletRecord record : oaCWalletRecordIPage.getRecords()) {
            WalletRecordResult recordResult=new WalletRecordResult();
            ERecordType rType = ERecordType.findById(record.getRecordType());
            if (rType.getRecordType().equals(0)){
                recordResult.setActualAmount(String.format("+ %s", record.getActualAmount().toString()));
            } else {
                recordResult.setActualAmount(String.format("- %s", record.getActualAmount().toString()));
            }
            recordResult.setRecordType(rType.getRecordType());
            recordResult.setTransactionTime(new DateToStringConverter().convert(record.getTransactionTime()));
            recordResult.setRecordId(record.getRecordId());
            list.add(recordResult);
        }
       Map<String,Object> map=new HashMap<>();
        map.put("currentPageNum",oaCWalletRecordIPage.getCurrent());
        map.put("list",list);
        map.put("hasNext",list.size()==oaCWalletRecordIPage.getSize()?true:false);
        return map;
    }


    /**
     * 初始化用车制度
     * @return
     */
    private Map<String, Object> initVehicleSystem(){
        Map<String, Object> map = new HashMap<>(16);
        map.put("availableTime", "");
        map.put("availableModel", "");
        map.put("availableCity", "");
        return map;
    }

    /**
     * 初始化账单详情
     * @return
     */
    private Map<String, Object> initWalletRecord(){
        Map<String, Object> map = new HashMap<>(16);
        map.put("actualAmount", "");
        map.put("recordType", 0);
        map.put("transactionTime", "");
        map.put("transactionSerialNo", "");
        return map;
    }

    /**
     * 封装公共查询方法
     * @param userId 用户id
     * @param tag 租户
     * @param recordType 类型
     * @param current 分页当前页从1开始
     * @return
     */
    private IPage selectWalletRecordPageByRecordType(Long userId, String tag, Long current, Integer... recordType){
        IPage<OaCWalletRecord> oaCWalletRecordIPage = new Page<>();
        oaCWalletRecordIPage.setCurrent(current);
        // 钱包记录
        oaCWalletRecordIPage = oaCWalletRecordMapper.selectPage(oaCWalletRecordIPage,
                Wrappers.<OaCWalletRecord>lambdaQuery()
                        .eq(OaCWalletRecord::getUserId, userId)
                        .eq(OaCWalletRecord::getTag, tag)
                        .eq(OaCWalletRecord::getIsTransaction, EIsTransaction.paySuccess.getValue())
                        .in(OaCWalletRecord::getRecordType, recordType)
                        .orderByDesc(OaCWalletRecord::getCreateTime)
        );
        List list = new ArrayList();
        for (OaCWalletRecord record : oaCWalletRecordIPage.getRecords()) {
            Map<String, Object> map = new HashMap<>(16);
            ERecordType rType = ERecordType.findById(record.getRecordType());
            if (rType.getRecordType().equals(0)){
                map.put("actualAmount", String.format("+ %s", record.getActualAmount().toString()));
                // 收入
                map.put("amountType", 0);
            } else {
                map.put("actualAmount", String.format("- %s", record.getActualAmount().toString()));
                // 支出
                map.put("amountType", 1);
            }
            map.put("recordType", rType.getValue());
            map.put("transactionTime", new DateToStringConverter().convert(record.getTransactionTime()));
            map.put("recordId", record.getRecordId().toString());

            list.add(map);
        }
        // 出参
        IPage result = new Page();
        result.setCurrent(oaCWalletRecordIPage.getCurrent());
        result.setTotal(oaCWalletRecordIPage.getTotal());
        result.setSize(oaCWalletRecordIPage.getSize());
        result.setPages(oaCWalletRecordIPage.getPages());
        result.setRecords(list);
        return result;
    }
    /**
     * 用户公务额度列表
     * @param userId 用户id
     * @param moneyType 额度类型（0 全部 1 收入 2 支出）
     * @param current 当前页
     * @return
     */
    /*@Override
    public IPage<OaCWalletRecord> selectOfficialMoneyPage(Long userId, Integer recordType, long current) {
        IPage<OaCWalletRecord> iPage = new Page<>();
        iPage.setCurrent(current);
        LambdaQueryWrapper<OaCWalletRecord> wrapper = Wrappers.<OaCWalletRecord>lambdaQuery()
                .eq(OaCWalletRecord::getUserId, userId)
                .eq(OaCWalletRecord::getDeleted, "0");
        *//*if (moneyType != 0){
            wrapper.eq(OaCWalletRecord::getMoneyType, moneyType);
        }*//*
        IPage<OaCWalletRecord> page = oaCWalletRecordMapper.selectPage(iPage, wrapper);
        IPage resultPage = new Page();
        resultPage.setCurrent(page.getCurrent());
        resultPage.setSize(page.getSize());
        resultPage.setTotal(page.getTotal());
        resultPage.setPages(page.getPages());
        List<Map<String, Object>> list = new ArrayList<>();
        for (OaCWalletRecord oaCWalletRecord : page.getRecords()) {
            Map<String, Object> map = new HashMap<>(16);
            map.put("recordId",oaCWalletRecord.getRecordId());
            map.put("orderNo",oaCWalletRecord.getOrderNo());
            map.put("actualAmount",oaCWalletRecord.getActualAmount());
            map.put("discountedAmount",oaCWalletRecord.getDiscountedAmount());
            map.put("walletBalance",oaCWalletRecord.getWalletBalance());
            map.put("personalOfficialBalance",oaCWalletRecord.getPersonalOfficialBalance());
            map.put("deptOfficialBalance",oaCWalletRecord.getDeptOfficialBalance());
            map.put("recordType",oaCWalletRecord.getRecordType());
            map.put("recordTypeName", ERecordType.findById(oaCWalletRecord.getRecordType()).getValue());
            map.put("transactionTime",oaCWalletRecord.getTransactionTime());
            map.put("transactionOrderNo",oaCWalletRecord.getTransactionOrderNo());
            map.put("transactionSerialNo",oaCWalletRecord.getTransactionSerialNo());
            list.add(map);
        }
        resultPage.setRecords(list);
        return resultPage;
    }*/

    /**
     * 用户公务额度列表详情
     * @param userId 用户id
     * @param recordId 列表id
     * @return
     */
    /*@Override
    public Map<String, Object> getOfficialMoneyDetails(Long userId, Long recordId) {
        LambdaQueryWrapper<OaCWalletRecord> wrapper = Wrappers.<OaCWalletRecord>lambdaQuery()
                .eq(OaCWalletRecord::getUserId, userId)
                .eq(OaCWalletRecord::getRecordId, recordId)
                .eq(OaCWalletRecord::getDeleted, "0");
        OaCWalletRecord oaCWalletRecord = oaCWalletRecordMapper.selectOne(wrapper);
        Map<String, Object> map = new HashMap<>(16);
        if (oaCWalletRecord == null){
            return map;
        }
        map.put("recordId",oaCWalletRecord.getRecordId());
        map.put("orderNo",oaCWalletRecord.getOrderNo());
        map.put("actualAmount",oaCWalletRecord.getActualAmount());
        map.put("discountedAmount",oaCWalletRecord.getDiscountedAmount());
        map.put("walletBalance",oaCWalletRecord.getWalletBalance());
        map.put("personalOfficialBalance",oaCWalletRecord.getPersonalOfficialBalance());
        map.put("deptOfficialBalance",oaCWalletRecord.getDeptOfficialBalance());
        map.put("recordType",oaCWalletRecord.getRecordType());
        map.put("recordTypeName", ERecordType.findById(oaCWalletRecord.getRecordType()).getValue());
        map.put("transactionTime",oaCWalletRecord.getTransactionTime());
        map.put("transactionOrderNo",oaCWalletRecord.getTransactionOrderNo());
        map.put("transactionSerialNo",oaCWalletRecord.getTransactionSerialNo());
        return map;
    }*/
}
